<?php
//
//	file: install_att/install.php
//	author: ptirhiik
//	begin: 13/02/2006
//	version: 1.6.3 - 27/06/2007
//	license: http://opensource.org/licenses/gpl-license.php GNU General Public License (GPL)
//
//	based on : attachment_mod copyright (c) 2002 Meik Sievertsen (acydburn)
//

define('IN_PHPBB', true);
define('IN_INSTALL', true);

$phpbb_root_path = './../';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
$requester = 'install_att/install';

include($phpbb_root_path . 'common.'.$phpEx);
include($config->url('includes/class_install'));
include($config->url('includes/class_cp'));
include($config->url('includes/attach/class_attach'));

// script def
$requester = 'install_att/' . basename(__FILE__, '.' . $phpEx);

// constants
define('ROWS_A_TURN', 500);

// Old attachmod tables
define('OLD_ATTACH_CONFIG_TABLE', $table_prefix . 'attachments_config');
define('OLD_EXTENSION_GROUPS_TABLE', $table_prefix . 'extension_groups');
define('OLD_EXTENSIONS_TABLE', $table_prefix . 'extensions');
define('OLD_FORBIDDEN_EXTENSIONS_TABLE', $table_prefix . 'forbidden_extensions');
define('OLD_ATTACHMENTS_DESC_TABLE', $table_prefix . 'attachments_desc');
define('OLD_ATTACHMENTS_TABLE', $table_prefix . 'attachments');
define('OLD_QUOTA_TABLE', $table_prefix . 'attach_quota');
define('OLD_QUOTA_LIMITS_TABLE', $table_prefix . 'quota_limits');

// tpls
function welcome_form()
{
	global $page;
?><form name="post" method="post" action="<?php echo $page->url(); ?>"><br /><br /><div align="center"><table cellpadding="4" cellspacing="1" border="0" width="80%" class="background">
<tr><th><?php echo sprintf($page->lang('AT_welcome'), ATTACH_CURRENT_VERSION); ?></th></tr>
<tr><td align="justify" class="row1"><?php echo sprintf($page->lang('AT_welcome_explain'), ATTACH_CURRENT_VERSION); ?><br /><br /><br /></td></tr>
<tr><td align="center" class="row2"><?php echo $page->lang('AT_start'); ?>: <input name="submit" type="submit" value="<?php echo $page->lang('AT_proceed'); ?>" /></td></tr>
</table></div><?php $page->hide(); ?></form>
<?php
}

function percent_box($title, $percent)
{
	global $page;
	$mult = 2;
	$page->output('<table cellpadding="1" cellspacing="0" border="0"><tr><td>' . $title . ':&nbsp;</td><td style="width: ' . (100 * $mult) . 'px; height: 13px; background-color: #FEFEFF; border: 1px #98AAB1 solid;"><div style="width: ' . ($percent * $mult). 'px; height: 13px; background-color: #00D000;"></div></td></tr></table>');
}

// steps
$steps = array(
	'AT_welcome',
	'AT_previous_version',
	'AT_db',

//-- specific to attachmod migration
	'AT_migrate_config',
	'AT_migrate_extensions',
	'AT_migrate_quota',
	'AT_migrate_attach',
	'AT_drop_tables',

//-- end of process
	'AT_patch',
	'AT_end',
);

// parms (not set is : type => TYPE_INT, default => 0)
$parms_def = array(
	'step' => array('list' => &$steps),
	'atpvch' => array('type' => TYPE_NO_HTML, 'default' => ''),
	'atpvreg' => array('type' => TYPE_NO_HTML, 'default' => ''),
	'db' => '',

	'mcfg' => '',
	'mext' => '',
	'mquota' => '',
	'mattach' => '',
	'mdbdrop' => array('type' => TYPE_NO_HTML, 'default' => ''),

	'catt' => '',
	'tatt' => '',

	'atp' => '',
// errors in droping tables
	'errcfg' => '',
	'errextgrp' => '',
	'errext' => '',
	'errextforb' => '',
);

// step functions
function step()
{
	global $parms, $steps;
	return $steps[ $parms['step'] ];
}
function next_step($step='')
{
	global $page, $parms, $steps;
	if ( !empty($step) )
	{
		$t_steps = array_flip($steps);
		$parms['step'] = $t_steps[$step];
	}
	else
	{
		$parms['step']++;
	}
	$page->set_parms($parms);
}

function read_file($file)
{
	$data = @fread(@fopen($file, 'r'), @filesize($file));
	return $data ? "\n" . trim($data) : '';
}


function encode_new_permissions($forums_list)
{
	$res = '';
	if ( !empty($forums_list) )
	{
		$res = substr(',' . implode(',', array_map('dechex', $forums_list)) . ',', 0, 255);
		$res = substr($res, 0, strrpos(',' . $res, ','));
	}
	return $res;
}
function decode_old_permissions($forum_permissions)
{
	$one_char_encoding = '#';
	$two_char_encoding = '.';
	$auth = array();
	$auth_len = 1;
	$strlen_forum_permissions = strlen($forum_permissions);
	for ($pos = 0; $pos < $strlen_forum_permissions; $pos += $auth_len)
	{
		$forum_auth = substr($forum_permissions, $pos, 1);
		if ($forum_auth == $one_char_encoding)
		{
			$auth_len = 1;
			continue;
		}
		else if ($forum_auth == $two_char_encoding)
		{
			$auth_len = 2;
			$pos--;
			continue;
		}
		$forum_auth = substr($forum_permissions, $pos, $auth_len);
		$forum_id = base64_unpack($forum_auth);
		$auth[] = intval($forum_id);
	}
	return $auth;
}
function base64_unpack($string)
{
	$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-';
	$base = strlen($chars);

	$length = strlen($string); 
	$number = 0; 

	for($i = 1; $i <= $length; $i++)
	{ 
		$pos = $length - $i; 
		$operand = strpos($chars, substr($string,$pos,1));
		$exponent = pow($base, $i-1); 
		$decValue = $operand * $exponent; 
		$number += $decValue; 
	} 

	return $number; 
}

//--------------------------------------
//
// Start the process
//
//--------------------------------------

// parms reading
$parms = array();
foreach ( $parms_def as $parm => $data )
{
	$type = empty($data) || !isset($data['type']) ? TYPE_INT : $data['type'];
	$default = empty($data) || !isset($data['default']) ? (($type == TYPE_INT) ? 0 : '') : $data['default'];
	$list = empty($data) || !isset($data['list']) ? '' : $data['list'];
	$parms[$parm] = _read($parm, $type, $default, $list);
}

// start
$page = new page($requester, '', 'lang_CH_install_attach');
$page->set_parms($parms);
$page->sub_title = '';

// set version
$lang['Script_title'] = sprintf($lang['Script_title'], ATTACH_CURRENT_VERSION);

// log in
$session = new light_session();
$session->log_in(ADMIN);

// send welcome
if ( step() == 'AT_welcome' )
{
	$page->header();
	next_step();
	welcome_form();
	$page->footer();
}

// detect attachement mod
if ( step() == 'AT_previous_version' )
{
	// remove any old way install marker
	$sql = 'DELETE FROM ' . CONFIG_TABLE . '
				WHERE config_name = \'mod_attachmod_CH\'';
	$db->sql_query($sql, false, __LINE__, __FILE__);

	// get actual version
	$parms['atpvch'] = '';
	$sql = 'SELECT config_value
				FROM ' . CONFIG_TABLE . '
				WHERE config_name = \'mod_attachment_CH\'';
	$result = $db->sql_query($sql, false, __LINE__, __FILE__);
	if ( $row = $db->sql_fetchrow($result) )
	{
		$parms['atpvch'] = $row['config_value'];
	}
	$db->sql_freeresult($result);

	// verify if attachmod was present
	$parms['atpvreg'] = '';
	$sql = 'SELECT config_value
				FROM ' . OLD_ATTACH_CONFIG_TABLE . '
				WHERE config_name = \'attach_version\'';
	if ( $result = $db->sql_query($sql, false, __LINE__, __FILE__, false) )
	{
		$parms['atpvreg'] = ($row = $db->sql_fetchrow($result)) ? $row['config_value'] : $page->lang('Unknown');
		if ( empty($parms['atpvreg']) )
		{
			$parms['atpvreg'] = '2.4.3';
		}
	}
	next_step();
}

// display previous version
if ( !empty($parms['atpvch']) )
{
	$page->output(sprintf($page->lang('AT_previous_version_CH'), $parms['atpvch']));
}
else if ( !empty($parms['atpvreg']) )
{
	$page->output(sprintf($page->lang('AT_previous_version_REG'), $parms['atpvreg']));
}

// -----------------------------------------
//
// create or upgrade the database structure
//
// -----------------------------------------
if ( step() == 'AT_db' )
{
	// get the db install layer
	if ( !($sql_layer = $db->get_layer()) )
	{
		$page->critical_error('AT_db_not_supported');
	}
	if ( $sql_layer['SCHEMA'] == 'postgres' )
	{
		$sql_layer['SCHEMA'] = 'pgsql';
	}
	$dbi_layer = 'dbi_' . $sql_layer['SCHEMA'];

	// include the layers
	include($config->url('includes/class_xml'));
	include($config->url('includes/db/class_dbi'));
	include($config->url('includes/db/class_' . $dbi_layer));

	// read the sql instructions
	$schemas = array();
	switch ( $parms['atpvch'] )
	{
		case '1.0.0':
		case '1.0.2':
			$schemas[] = 'schema_100';
			break;

		case '1.0.4':
		case '1.0.6':

		// new install
		break;
		default:
			$schemas[] = 'schema_ch';
			break;
	}

	// process the schemas
	$xml_parser = new xml_parser();
	$dbi = new $dbi_layer($table_prefix);
	$count_schemas = count($schemas);
	for ( $i = 0; $i < $count_schemas; $i++ )
	{
		// read & parse the XML schema
		$actions = false;
		if ( ($xml_name = phpbb_realpath($phpbb_root_path . 'install_att/schemas/' . $schemas[$i] . '.xml')) && ($handler = @fopen($xml_name, 'r')) )
		{
			$xml = trim(fread($handler, filesize($xml_name)));
			fclose($handler);
			unset($handler);
			$actions = empty($xml) ? false : $xml_parser->parse($xml);
			unset($xml);
			if ( $actions === false )
			{
				$page->critical_error($xml_parser->errmsg);
			}
		}

		// process the sqls
		if ( $actions && isset($actions['cdata']) && ($count_actions = count($actions['cdata'])) )
		{
			for ( $j = 0; $j < $count_actions; $j++ )
			{
				$sqls = isset($actions['cdata'][$j]['actions']) ? $dbi->process($actions['cdata'][$j]['actions']) : false;
				unset($actions['cdata'][$j]);

				$count_sqls = $sqls ? count($sqls) : 0;
				for ( $k = 0; $k < $count_sqls; $k++ )
				{
					$result = $db->sql_query($sqls[$k], false, __LINE__, __FILE__, false);
					if ( $result === false )
					{
						$sql_error = $db->sql_error();
						$page->error(sprintf($page->lang('AT_sql_already_done'), ($sql_error['message'] ? $sql_error['message'] . ': ' : '') . $sqls[$k]));
					}
					else if ( $result !== true )
					{
						$db->sql_freeresult($result);
					}
					unset($result);
				}
				unset($sqls);
			}
		}
		unset($actions);
	}
	unset($dbi);
	unset($xml_parser);
	unset($schemas);

	// jump to end if not a migration from attachmod
	$parms['db'] = true;
	next_step(empty($parms['atpvreg']) ? 'AT_patch' : '');
	$page->loop();
}
if ( !empty($parms['db']) )
{
	$page->output(empty($parms['atpvch']) ? 'AT_db_done' : 'AT_db_upgraded');
}


// --------------------------------------------
//
// migrate from attachmod to attachment for CH
//
// --------------------------------------------

// config table
if ( step() == 'AT_migrate_config' )
{
	// read the old config
	$sql = 'SELECT *
				FROM ' . OLD_ATTACH_CONFIG_TABLE;
	if ( $result = $db->sql_query($sql, false, __LINE__, __FILE__) )
	{
		$old_config = array();
		while ( $row = $db->sql_fetchrow($result) )
		{
			$old_config[ $row['config_name'] ] = $row['config_value'];
		}
		$db->sql_freeresult($result);

		// read new config
		$keys = array();
		$db->sql_stack_reset();
		$sql = 'SELECT *
					FROM ' . ATT_CONFIG_TABLE;
		$result = $db->sql_query($sql, false, __LINE__, __FILE__);
		while ( $row = $db->sql_fetchrow($result) )
		{
			if ( isset($old_config[ $row['config_name'] ]) && ($old_config[ $row['config_name'] ] != $row['config_value']) )
			{
				$keys[] = $db->sql_escape_string($row['config_name']);
				$fields = array(
					'config_name' => $row['config_name'],
					'config_value' => $old_config[ $row['config_name'] ],
				);
				$db->sql_stack_statement($fields);
			}
		}
		$db->sql_freeresult($result);
		unset($old_config);

		// reinsert the old values
		if ( !empty($keys) )
		{
			$sql = 'DELETE FROM ' . ATT_CONFIG_TABLE . '
						WHERE config_name IN(\'' . implode('\', \'', $keys) . '\')';
			$db->sql_query($sql, false, __LINE__, __FILE__);

			$db->sql_stack_insert(ATT_CONFIG_TABLE, false, __LINE__, __FILE__);
		}
		$parms['mcfg'] = true;
	}
	next_step();
	$page->loop();
}
if ( intval($parms['mcfg']) )
{
	$page->output('AT_old_config_recovered');
}


// extensions + extension groups recovering
if ( step() == 'AT_migrate_extensions' )
{
	// check extensions table
	$sql = 'SELECT *
				FROM ' . OLD_EXTENSIONS_TABLE . '
				LIMIT 1';
	if ( $ext_table = ($result = $db->sql_query($sql, false, __LINE__, __FILE__)) )
	{
		$db->sql_freeresult($result);
	}
	// check extension groups table
	$sql = 'SELECT *
				FROM ' . OLD_EXTENSION_GROUPS_TABLE . '
				LIMIT 1';
	if ( $ext_groups_table = ($result = $db->sql_query($sql, false, __LINE__, __FILE__)) )
	{
		$db->sql_freeresult($result);
	}
	// check forbidden extensions table
	$sql = 'SELECT *
				FROM ' . OLD_FORBIDDEN_EXTENSIONS_TABLE . '
				LIMIT 1';
	if ( $forbidden_ext_table = ($result = $db->sql_query($sql, false, __LINE__, __FILE__)) )
	{
		$db->sql_freeresult($result);
	}

	// we have extensions & groups
	if ( $ext_table && $ext_groups_table )
	{
		// reset the new tables : we gonna use the old settings
		$sql = 'TRUNCATE TABLE ' . ATT_EXT_GROUPS_TABLE;
		$db->sql_query($sql, false, __LINE__, __FILE__);

		$sql = 'TRUNCATE TABLE ' . ATT_EXTENSIONS_TABLE;
		$db->sql_query($sql, false, __LINE__, __FILE__);

		// get the old extension groups
		$ext_groups = array();
		$sql = 'SELECT *
					FROM ' . OLD_EXTENSION_GROUPS_TABLE . '
					ORDER BY group_id';
		$result = $db->sql_query($sql, false, __LINE__, __FILE__);
		while ( $row = $db->sql_fetchrow($result) )
		{
			$ext_groups[ intval($row['group_id']) ] = array(
				'ext_group_name' => $row['group_name'],
				'cat_id' => intval($row['cat_id']),
				'allow_group' => intval($row['allow_group']),
				'download_mode' => intval($row['download_mode']),
				'upload_icon' => $row['upload_icon'],
				'max_filesize' => intval($max_filesize),
				'forum_permissions' => encode_new_permissions(decode_old_permissions(trim($row['forum_permissions']))),
			);
		}
		$db->sql_freeresult($result);

		// re-create groups in the new table
		$match_ext_group_ids = array();
		if ( !empty($ext_groups) )
		{
			foreach ( $ext_groups as $old_ext_group_id => $fields )
			{
				$db->sql_statement($fields);
				$sql = 'INSERT INTO ' . ATT_EXT_GROUPS_TABLE . '
							(' . $db->sql_fields . ') VALUES(' . $db->sql_values . ')';
				$db->sql_query($sql, false, __LINE__, __FILE__);
				$match_ext_group_ids[$old_ext_group_id] = intval($db->sql_nextid());
			}
		}
		unset($ext_groups);

		// add the forbidden group
		$fields = array(
			'ext_group_name' => 'Forbidden',
			'cat_id' => DENIED_CAT,
			'allow_group' => 0,
			'download_mode' => INLINE_LINK,
			'upload_icon' => '',
			'max_filesize' => 0,
			'forum_permissions' => '',
		);
		$db->sql_statement($fields);
		$sql = 'INSERT INTO ' . ATT_EXT_GROUPS_TABLE . '
					(' . $db->sql_fields . ') VALUES(' . $db->sql_values . ')';
		$db->sql_query($sql, false, __LINE__, __FILE__);
		$forbidden_ext_group_id = intval($db->sql_nextid());

		// get the old extensions
		$sql = 'SELECT *
					FROM ' . OLD_EXTENSIONS_TABLE . '
					ORDER BY extension';
		$result = $db->sql_query($sql, false, __LINE__, __FILE__);
		$db->sql_stack_reset();
		while ( $row = $db->sql_fetchrow($result) )
		{
			$fields = array(
				'extension' => strtolower(trim($row['extension'])),
				'ext_group_id' => intval($match_ext_group_ids[ intval($row['group_id']) ]) ? intval($match_ext_group_ids[ intval($row['group_id']) ]) : 0,
				'ext_comment' => trim($row['comment']),
			);
			$db->sql_stack_statement($fields);
		}
		$db->sql_freeresult($result);
		unset($match_ext_group_ids);
		$db->sql_stack_insert(ATT_EXTENSIONS_TABLE, false, __LINE__, __FILE__);

		// deal with forbidden extensions
		if ( $forbidden_ext_table )
		{
			// reread extensions
			$extensions = array();
			$sql = 'SELECT extension
						FROM ' . ATT_EXTENSIONS_TABLE . '
						ORDER BY extension';
			$result = $db->sql_query($sql, false, __LINE__, __FILE__);
			while ( $row = $db->sql_fetchrow($result) )
			{
				$extensions[ $row['extension'] ] = true;
			}
			$db->sql_freeresult($result);

			// get the old forbidden extensions
			$to_update = array();
			$sql = 'SELECT *
						FROM ' . OLD_FORBIDDEN_EXTENSIONS_TABLE . '
						ORDER BY extension';
			$result = $db->sql_query($sql, false, __LINE__, __FILE__);
			$db->sql_stack_reset();
			while ( $row = $db->sql_fetchrow($result) )
			{
				$fields = array(
					'extension' => strtolower(trim($row['extension'])),
					'ext_group_id' => intval($forbidden_ext_group_id),
					'ext_comment' => '',
				);
				if ( isset($extensions[ $fields['extension'] ]) )
				{
					$to_update[] = $db->sql_escape_string($fields['extension']);
				}
				else
				{
					$db->sql_stack_statement($fields);
				}
			}
			$db->sql_freeresult($result);
			unset($extensions);
			$db->sql_stack_insert(ATT_EXTENSIONS_TABLE, false, __LINE__, __FILE__);
			if ( !empty($to_update) )
			{
				$sql = 'UPDATE ' . ATT_EXTENSIONS_TABLE . '
							SET ext_group_id = ' . intval($forbidden_ext_group_id) . '
							WHERE extension IN(\'' . implode('\', \'', $to_update) . '\')';
				$db->sql_query($sql, false, __LINE__, __FILE__);
			}
			unset($to_update);
		}
		unset($forbidden_ext_group_id);
		$parms['mext'] = true;
	}
	next_step();
	$page->loop();
}
if ( !empty($parms['mext']) )
{
	$page->output('AT_old_extensions_recovered');
}

// quotas
if ( step() == 'AT_migrate_quota' )
{
	// check the quota table
	$sql = 'SELECT *
				FROM ' . OLD_QUOTA_TABLE . '
				LIMIT 1';
	if ( $quota_table = ($result = $db->sql_query($sql, false, __LINE__, __FILE__, false)) )
	{
		$db->sql_freeresult($result);
	}
	// check quota limits table
	$sql = 'SELECT *
				FROM ' . OLD_QUOTA_LIMITS_TABLE . '
				LIMIT 1';
	if ( $quota_limits_table = ($result = $db->sql_query($sql, false, __LINE__, __FILE__, false)) )
	{
		$db->sql_freeresult($result);
	}

	// we have quota & quota limits
	if ( $quota_table && $quota_limits_table )
	{
		// we gonna use the old data
		$sql = 'TRUNCATE TABLE ' . ATT_QUOTA_TABLE;
		$db->sql_query($sql, false, __LINE__, __FILE__);

		$sql = 'TRUNCATE TABLE ' . ATT_QUOTA_LIMITS_TABLE;
		$db->sql_query($sql, false, __LINE__, __FILE__);

		// get old quota limits
		$sql = 'SELECT *
					FROM ' . OLD_QUOTA_LIMITS_TABLE . '
					ORDER BY quota_limit';
		$result = $db->sql_query($sql, false, __LINE__, __FILE__);
		$quota_limits = array();
		while ( $row = $db->sql_fetchrow($result) )
		{
			$quota_limits[ intval($row['quota_limit_id']) ] = array(
				'quota_desc' => trim($row['quota_desc']),
				'quota_limit' => intval($row['quota_limit']),
			);
		}
		$db->sql_freeresult($result);

		// re-create quota limits in the new table
		$match_quota_limit_ids = array();
		if ( !empty($quota_limits) )
		{
			foreach ( $quota_limits as $old_quota_limit_id => $fields )
			{
				$db->sql_statement($fields);
				$sql = 'INSERT INTO ' . ATT_QUOTA_LIMITS_TABLE . '
							(' . $db->sql_fields . ') VALUES(' . $db->sql_values . ')';
				$db->sql_query($sql, false, __LINE__, __FILE__);
				$match_quota_limit_ids[$old_quota_limit_id] = intval($db->sql_nextid());
			}
		}
		unset($quota_limits);

		// re-create quota : we retain only existing groups
		$sql = 'SELECT q.*, g.group_id
					FROM ' . OLD_QUOTA_TABLE . ' q, ' . GROUPS_TABLE . ' g
					WHERE (q.user_id <> 0 AND g.group_user_id = q.user_id)
						OR (q.group_id <> 0 AND g.group_id = q.group_id)
					ORDER BY q.group_id, q.user_id';
		$result = $db->sql_query($sql, false, __LINE__, __FILE__);
		$db->sql_stack_reset();
		while ( $row = $db->sql_fetchrow($result) )
		{
			$fieds = array(
				'group_id' => intval($row['group_id']),
				'quota_type' => intval($row['quota_type']),
				'quota_limit_id' => intval($match_quota_limit_ids[ intval($row['quota_limit_id']) ]) ? intval($match_quota_limit_ids[ intval($row['quota_limit_id']) ]) : 0,
			);
			if ( intval($fields['quota_limit_id']) )
			{
				$db->sql_stack_statement($fields);
			}
		}
		$db->sql_freeresult($result);
		unset($match_quota_limit_ids);
		$db->sql_stack_insert(ATT_QUOTA_TABLE, false, __LINE__, __FILE__);

		$parms['mquota'] = true;
	}
	next_step();
	$page->loop();
}
if ( !empty($parms['mquota']) )
{
	$page->output('AT_old_quota_recovered');
}


// now the important part : recover attachments
if ( step() == 'AT_migrate_attach' )
{
	// check attachment desc table
	$sql = 'SELECT *
				FROM ' . OLD_ATTACHMENTS_DESC_TABLE . '
				LIMIT 1';
	if ( $attach_desc_table = ($result = $db->sql_query($sql, false, __LINE__, __FILE__, false)) )
	{
		$db->sql_freeresult($result);
	}
	// check attachment links table
	$sql = 'SELECT *
				FROM ' . OLD_ATTACHMENTS_TABLE . '
				LIMIT 1';
	if ( $attach_links_table = ($result = $db->sql_query($sql, false, __LINE__, __FILE__, false)) )
	{
		$db->sql_freeresult($result);
	}

	// we have attachments links & desc
	if ( $attach_links_table && $attach_desc_table )
	{
		if ( !intval($parms['tatt']) )
		{
			// we gonna use old data
			$sql = 'TRUNCATE TABLE ' . ATT_DESC_TABLE;
			$db->sql_query($sql, false, __LINE__, __FILE__);

			$sql = 'TRUNCATE TABLE ' . ATT_LINKS_TABLE;
			$db->sql_query($sql, false, __LINE__, __FILE__);

			// count the existing attachments
			$sql = 'SELECT COUNT(attach_id) AS count_attach_id
						FROM ' . OLD_ATTACHMENTS_DESC_TABLE;
			$result = $db->sql_query($sql, false, __LINE__, __FILE__);
			$parms['tatt'] = ($row = $db->sql_fetchrow($result)) ? intval($row['count_attach_id']) + 1 : 1;
			$db->sql_freeresult($result);
		}
		$total = intval($parms['tatt']) - 1;
		$start = intval($parms['catt']);
		$row_a_turn = intval(ROWS_A_TURN / 5);
		$attachments = array();
		$sql = 'SELECT *
					FROM ' . OLD_ATTACHMENTS_DESC_TABLE . '
					ORDER BY attach_id
					LIMIT ' . intval($start) . ', ' . intval($row_a_turn);
		$result = $db->sql_query($sql, false, __LINE__, __FILE__);
		while ( $row = $db->sql_fetchrow($result) )
		{
			$attachments[ intval($row['attach_id']) ] = array(
				'physical_filename' => basename(trim($row['physical_filename'])),
				'real_filename' => basename(trim($row['real_filename'])),
				'download_count' => intval($row['download_count']),
				'file_comment' => trim($row['comment']),
				'extension' => strtolower(trim($row['extension'])),
				'mimetype' => trim($row['mimetype']),
				'filesize' => intval($row['filesize']),
				'filetime' => intval($row['filetime']),
				'thumbnail' => intval($row['thumbnail']) ? 1 : 0,
				'width' => isset($row['width']) ? intval($row['width']) : -1,
				'height' => isset($row['height']) ? intval($row['height']) : -1,
			);
		}
		$db->sql_freeresult($result);
		$count_attachments = count($attachments);

		// create the attachments in the new table
		$match_attach_ids = array();
		if ( $count_attachments )
		{
			foreach ( $attachments as $old_attach_id => $fields )
			{
				$db->sql_statement($fields);
				$sql = 'INSERT INTO ' . ATT_DESC_TABLE . '
							(' . $db->sql_fields . ') VALUES(' . $db->sql_values . ')';
				$db->sql_query($sql, false, __LINE__, __FILE__);
				$match_attach_ids[$old_attach_id] = intval($db->sql_nextid());
			}
		}
		unset($attachments);

		// deal with the all attachment links
		if ( !empty($match_attach_ids) )
		{
			$sql = 'SELECT *
						FROM ' . OLD_ATTACHMENTS_TABLE . '
						WHERE attach_id IN(' . implode(', ', array_keys($match_attach_ids)) . ')
						ORDER BY attach_id';
			$result = $db->sql_query($sql, false, __LINE__, __FILE__);
			$db->sql_stack_reset();
			while ( $row = $db->sql_fetchrow($result) )
			{
				$fields = array(
					'attach_id' => intval($match_attach_ids[ intval($row['attach_id']) ]),
					'post_id' => intval($row['post_id']),
					'privmsgs_id' => intval($row['privmsgs_id']),
					'user_id' => intval($row['user_id_1']),
				);
				$db->sql_stack_statement($fields);
			}
			$db->sql_freeresult($result);
			$db->sql_stack_insert(ATT_LINKS_TABLE, false, __LINE__, __FILE__);
		}
		unset($match_attach_ids);

		$parms['catt'] = (intval($parms['catt']) ? intval($parms['catt']) : 0) + $count_attachments;
		$total_done = intval($parms['tatt']) - 1 - intval($parms['catt']);
		$percent_done = max(1, min(100, round((100 * $total_done) / max(1, intval($parms['tatt']) - 1))));

		// send percent box
		percent_box(sprintf($page->lang('AT_attach_percent'), intval($parms['catt']), intval($parms['tatt']) - 1), $percent_done);
		if ( $count_attachments )
		{
			$page->loop($parms);
		}
	}
	next_step();
	$page->loop();
}
if ( intval($parms['tatt']) )
{
	$page->output(sprintf($page->lang('AT_attach_done'), intval($parms['tatt']) - 1));
}

// do some definitive cleaning
$old_tables = array(
	OLD_ATTACH_CONFIG_TABLE,
	OLD_EXTENSION_GROUPS_TABLE,
	OLD_EXTENSIONS_TABLE,
	OLD_FORBIDDEN_EXTENSIONS_TABLE,
	OLD_ATTACHMENTS_DESC_TABLE,
	OLD_ATTACHMENTS_TABLE,
	OLD_QUOTA_TABLE,
	OLD_QUOTA_LIMITS_TABLE,
);
if ( step() == 'AT_drop_tables' )
{
	$failed = array();
	foreach ( $old_tables as $idx => $table )
	{
		$sql = 'DROP TABLE ' . $table;
		if ( !$db->sql_query($sql, false, __LINE__, __FILE__, false) )
		{
			$failed[] = $idx + 1;
		}
	}
	$parms['mdbdrop'] = $failed ? implode(',', $failed) : 'done';
	next_step();
}
if ( !empty($parms['mdbdrop']) )
{
	$tfailed = array_map('intval', explode(',', $parms['mdbdrop']));
	$failed = array();
	$count_tfailed = count($tfailed);
	for ( $i = 0; $i < $count_tfailed; $i++ )
	{
		if ( intval($tfailed[$i]) && isset($old_tables[ (intval($tfailed[$i]) - 1) ]) )
		{
			$failed[] = $old_tables[ (intval($tfailed[$i]) - 1) ];
		}
	}
	unset($tfailed);
	$page->output($failed ? sprintf($page->lang('AT_old_tables_error'), implode(', ', $failed)) : 'AT_old_tables_succeed');
	unset($failed);
}


// --------------------------
//
// finalize the installation
//
// --------------------------
if ( step() == 'AT_patch' )
{
	$config->set('mod_attachment_CH', ATTACH_CURRENT_VERSION, true);

	// instantiate the acting user
	$sav_lang = $lang;
	$user = new user();
	$user->read($session->user_id);

	// patch the panels
	$cp_panels = new cp_panels($requester);
	$cp_panels->read(true);
	$cp_panels->patch(true);

	// remove the acting user
	unset($user);
	$lang = $sav_lang;

	$parms['atp'] = true;
	next_step();
}
if ( !empty($parms['atp']) )
{
	$page->output('AT_panels_patched');
}

// all is done, recache
if ( step() == 'AT_end' )
{
	$sql = 'DELETE FROM ' . USERS_CACHE_TABLE;
	$db->sql_query($sql, false, __LINE__, __FILE__);

	$page->error(empty($parms['atpvch']) ? 'AT_install_done' : 'AT_install_upgraded');
	$page->critical_error('AT_return_to_board');
}

// send page
$page->header();
$page->footer();

?>